package com.ruoyi.tzai.service.impl;

import java.util.Arrays;
import java.util.Date;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.tzai.domain.TaskQueue;
import com.ruoyi.tzai.domain.TaskStep;
import com.ruoyi.tzai.mapper.TaskQueueMapper;
import com.ruoyi.tzai.mapper.TaskStepMapper;
import com.ruoyi.tzai.service.INewsProcessService;
import com.ruoyi.tzai.service.ITaskQueueService;

/**
 * 任务队列Service业务层处理
 * 
 * @author tzai
 * @date 2025-11-12
 */
@Service
public class TaskQueueServiceImpl implements ITaskQueueService 
{
    private static final Logger log = LoggerFactory.getLogger(TaskQueueServiceImpl.class);

    @Autowired
    private TaskQueueMapper taskQueueMapper;

    @Autowired
    private TaskStepMapper taskStepMapper;

    @Autowired
    @Lazy
    private INewsProcessService newsProcessService;

    /**
     * 查询任务队列
     * 
     * @param taskId 任务队列主键
     * @return 任务队列
     */
    @Override
    public TaskQueue selectTaskQueueByTaskId(Long taskId)
    {
        return taskQueueMapper.selectTaskQueueByTaskId(taskId);
    }

    /**
     * 查询任务队列列表
     * 
     * @param taskQueue 任务队列
     * @return 任务队列
     */
    @Override
    public List<TaskQueue> selectTaskQueueList(TaskQueue taskQueue)
    {
        return taskQueueMapper.selectTaskQueueList(taskQueue);
    }

    /**
     * 新增任务队列
     * 
     * @param taskQueue 任务队列
     * @return 结果
     */
    @Override
    public int insertTaskQueue(TaskQueue taskQueue)
    {
        taskQueue.setCreateTime(DateUtils.getNowDate());
        return taskQueueMapper.insertTaskQueue(taskQueue);
    }

    /**
     * 修改任务队列
     * 
     * @param taskQueue 任务队列
     * @return 结果
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public int updateTaskQueue(TaskQueue taskQueue)
    {
        taskQueue.setUpdateTime(DateUtils.getNowDate());
        return taskQueueMapper.updateTaskQueue(taskQueue);
    }

    /**
     * 批量删除任务队列
     * 
     * @param taskIds 需要删除的任务队列主键
     * @return 结果
     */
    @Override
    public int deleteTaskQueueByTaskIds(Long[] taskIds)
    {
        return taskQueueMapper.deleteTaskQueueByTaskIds(taskIds);
    }

    /**
     * 删除任务队列信息
     * 
     * @param taskId 任务队列主键
     * @return 结果
     */
    @Override
    public int deleteTaskQueueByTaskId(Long taskId)
    {
        return taskQueueMapper.deleteTaskQueueByTaskId(taskId);
    }

    /**
     * 创建任务
     * 
     * @param articleId 文章ID
     * @param configJson 任务配置JSON
     * @return 任务ID
     */
    @Override
    @Transactional
    public Long createTask(Long articleId, String configJson)
    {
        log.info("创建任务: articleId={}", articleId);
        
        TaskQueue task = new TaskQueue();
        task.setArticleId(articleId);
        task.setTaskType("article_process");
        task.setPriority(0);
        task.setStatus("pending");
        task.setCurrentStepProgress(0);
        task.setTotalProgress(0);
        task.setRetryCount(0);
        task.setMaxRetry(3);
        task.setConfig(configJson);
        task.setIsCleaned(false);
        task.setCreateTime(new Date());
        
        taskQueueMapper.insertTaskQueue(task);
        
        log.info("任务创建成功: taskId={}", task.getTaskId());
        return task.getTaskId();
    }

    /**
     * 提交任务到队列
     * 
     * @param taskId 任务ID
     */
    @Override
    @Transactional
    public void submitTask(Long taskId)
    {
        TaskQueue task = taskQueueMapper.selectTaskQueueByTaskId(taskId);
        if (task == null) {
            throw new RuntimeException("任务不存在: " + taskId);
        }
        
        if (!"pending".equals(task.getStatus())) {
            log.warn("任务状态不是pending，无法提交: taskId={}, status={}", taskId, task.getStatus());
            return;
        }
        
        // 状态保持pending，由执行器处理
        log.info("任务已提交: taskId={}", taskId);
    }

    /**
     * 暂停任务
     * 
     * @param taskId 任务ID
     */
    @Override
    @Transactional
    public void pauseTask(Long taskId)
    {
        TaskQueue task = taskQueueMapper.selectTaskQueueByTaskId(taskId);
        if (task == null) {
            throw new RuntimeException("任务不存在: " + taskId);
        }
        
        if (!"running".equals(task.getStatus())) {
            log.warn("只能暂停运行中的任务: taskId={}, status={}", taskId, task.getStatus());
            return;
        }
        
        task.setStatus("paused");
        task.setUpdateTime(new Date());
        taskQueueMapper.updateTaskQueue(task);
        
        log.info("任务已暂停: taskId={}", taskId);
    }

    /**
     * 继续任务（支持断点续传）
     * 
     * @param taskId 任务ID
     */
    @Override
    @Transactional
    public void resumeTask(Long taskId)
    {
        TaskQueue task = taskQueueMapper.selectTaskQueueByTaskId(taskId);
        if (task == null) {
            throw new RuntimeException("任务不存在: " + taskId);
        }
        
        String status = task.getStatus();
        
        // 支持暂停、失败、运行中的任务恢复
        if ("paused".equals(status)) {
            // 暂停的任务：更新状态为pending，等待执行器处理
            task.setStatus("pending");
            task.setWorkerThread(null);
            task.setUpdateTime(new Date());
            taskQueueMapper.updateTaskQueue(task);
            log.info("任务已继续（从暂停状态）: taskId={}", taskId);
            
        } else if ("failed".equals(status) || "running".equals(status)) {
            // 失败或运行中的任务：使用断点续传恢复
            log.info("任务使用断点续传恢复: taskId={}, status={}", taskId, status);
            newsProcessService.resumeTask(taskId);
            
        } else if ("completed".equals(status)) {
            log.warn("任务已完成，无需恢复: taskId={}", taskId);
            
        } else {
            log.warn("任务状态不支持恢复: taskId={}, status={}", taskId, status);
        }
    }

    /**
     * 取消任务
     * 
     * @param taskId 任务ID
     */
    @Override
    @Transactional
    public void cancelTask(Long taskId)
    {
        TaskQueue task = taskQueueMapper.selectTaskQueueByTaskId(taskId);
        if (task == null) {
            throw new RuntimeException("任务不存在: " + taskId);
        }
        
        if ("completed".equals(task.getStatus()) || "cancelled".equals(task.getStatus())) {
            log.warn("任务已完成或已取消，无法取消: taskId={}, status={}", taskId, task.getStatus());
            return;
        }
        
        task.setStatus("cancelled");
        task.setCompletedAt(new Date());
        task.setUpdateTime(new Date());
        taskQueueMapper.updateTaskQueue(task);
        
        log.info("任务已取消: taskId={}", taskId);
    }

    /**
     * 重试任务
     * 
     * @param taskId 任务ID
     */
    @Override
    @Transactional
    public void retryTask(Long taskId)
    {
        TaskQueue task = taskQueueMapper.selectTaskQueueByTaskId(taskId);
        if (task == null) {
            throw new RuntimeException("任务不存在: " + taskId);
        }
        
        if (!"failed".equals(task.getStatus())) {
            log.warn("只能重试失败的任务: taskId={}, status={}", taskId, task.getStatus());
            return;
        }
        
        // 检查重试次数
        if (task.getRetryCount() >= task.getMaxRetry()) {
            throw new RuntimeException("任务已达到最大重试次数: " + task.getRetryCount());
        }
        
        task.setStatus("pending");
        task.setRetryCount(task.getRetryCount() + 1);
        task.setErrorMessage(null);
        task.setWorkerThread(null);
        task.setUpdateTime(new Date());
        taskQueueMapper.updateTaskQueue(task);
        
        log.info("任务重试: taskId={}, retryCount={}/{}", 
                 taskId, task.getRetryCount(), task.getMaxRetry());
    }

    /**
     * 获取任务状态
     * 
     * @param taskId 任务ID
     * @return 任务信息
     */
    @Override
    public TaskQueue getTaskStatus(Long taskId)
    {
        return taskQueueMapper.selectTaskQueueByTaskId(taskId);
    }

    /**
     * 原子性锁定任务
     * 
     * @param taskId 任务ID
     * @param workerThread 工作线程ID
     * @return 是否锁定成功
     */
    @Override
    @Transactional
    public boolean tryLockTask(Long taskId, String workerThread)
    {
        // 使用乐观锁，只有状态为pending的任务才能被锁定
        int updated = taskQueueMapper.updateTaskStatusWithLock(
            taskId, 
            "running", 
            Arrays.asList("pending"), 
            workerThread
        );
        
        if (updated > 0) {
            log.info("任务锁定成功: taskId={}, worker={}", taskId, workerThread);
            
            // 更新开始时间
            TaskQueue task = new TaskQueue();
            task.setTaskId(taskId);
            task.setStartedAt(new Date());
            task.setUpdateTime(new Date());
            taskQueueMapper.updateTaskQueue(task);
            
            return true;
        } else {
            log.warn("任务锁定失败: taskId={}", taskId);
            return false;
        }
    }

    /**
     * 查询待处理的任务
     * 
     * @param limit 限制数量
     * @return 任务列表
     */
    @Override
    public List<TaskQueue> selectPendingTasks(int limit)
    {
        return taskQueueMapper.selectPendingTasks(limit);
    }

    /**
     * 查询中断的任务（用于启动恢复）
     * 
     * @return 任务列表
     */
    @Override
    public List<TaskQueue> selectInterruptedTasks()
    {
        return taskQueueMapper.selectInterruptedTasks();
    }

    /**
     * 查询需要清理的任务
     * 
     * @param statuses 状态列表
     * @param days 完成后多少天
     * @return 任务列表
     */
    @Override
    public List<TaskQueue> selectTasksNeedCleanup(List<String> statuses, int days)
    {
        Date beforeDate = DateUtils.addDays(new Date(), -days);
        return taskQueueMapper.selectTasksNeedCleanup(statuses, beforeDate);
    }

    /**
     * 根据文章ID查询任务
     * 
     * @param articleId 文章ID
     * @return 任务
     */
    @Override
    public TaskQueue selectTaskQueueByArticleId(Long articleId)
    {
        return taskQueueMapper.selectTaskQueueByArticleId(articleId);
    }

    /**
     * 删除指定时间之前的任务
     * 
     * @param statuses 状态列表
     * @param days 天数
     * @return 删除数量
     */
    @Override
    @Transactional
    public int deleteTasksBefore(List<String> statuses, int days)
    {
        Date beforeDate = DateUtils.addDays(new Date(), -days);
        return taskQueueMapper.deleteTasksBefore(statuses, beforeDate);
    }

    /**
     * 插入任务步骤记录（使用独立事务，避免长时间异步任务中连接池回收问题）
     * 
     * @param taskStep 任务步骤
     * @return 结果
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public int insertTaskStep(TaskStep taskStep)
    {
        taskStep.setCreateTime(DateUtils.getNowDate());
        return taskStepMapper.insertTaskStep(taskStep);
    }

    /**
     * 查询任务的所有步骤
     * 
     * @param taskId 任务ID
     * @return 步骤列表
     */
    @Override
    public List<TaskStep> selectTaskStepsByTaskId(Long taskId)
    {
        return taskStepMapper.selectStepsByTaskId(taskId);
    }
}

